#include "app_serial.h"
#include "log/log.h"

//设置波特率
int app_serial_setBaudRate(Device *device, BaudRate rate)
{
    //获取串口当前配置属性
    struct termios attr;
    
    tcgetattr(device->fd, &attr);

    //修改波特率属性
    // cfsetispeed(&attr, rate);
    // cfsetospeed(&attr, rate);
    cfsetspeed(&attr, rate);

    //设置串口属性
    int result = tcsetattr(device->fd, TCSAFLUSH, &attr);
    if (result != 0)
    {
        log_error("设置波特率失败");
    }
        
    log_debug("设置波特率成功");
    return 0;
}

//设置校验位
int app_serial_setParity(Device *device, Parity parity)
{
    //获取串口当前配置属性
    struct termios attr;
    
    tcgetattr(device->fd, &attr);

    //修改校验位属性
    attr.c_cflag &= ~(PARENB|PARODD); //清除校验位
    attr.c_cflag |= parity; //设置停止位

    //设置串口属性
    int result = tcsetattr(device->fd, TCSAFLUSH, &attr);
    if (result != 0)
    {
        log_error("设置校验位失败");
    }
        
    log_debug("设置校验位成功");
    return 0;
}

//设置停止位
int app_serial_setStopBits(Device *device, StopBits stopBits)
{
    //获取串口当前配置属性
    struct termios attr;
    
    tcgetattr(device->fd, &attr);

    //修改停止位属性
    attr.c_cflag &= ~CSTOPB; //清除停止位
    attr.c_cflag |= stopBits; //设置停止位

    //设置串口属性
    int result = tcsetattr(device->fd, TCSAFLUSH, &attr);
    if (result != 0)
    {
        log_error("设置停止位失败");
    }
        
    log_debug("设置停止位成功");
    return 0;
}

//设置是否阻塞模式
int app_serial_setBlock(Device *device, int is_block)
{
    //获取串口当前配置属性
    struct termios attr;
    
    tcgetattr(device->fd, &attr);

    //修改阻塞属性
    if (is_block)
    {
        attr.c_cc[VMIN] = 1;//至少要读到一个字节才返回(阻塞)
        attr.c_cc[VTIME] = 0;//0 -> 一直等(阻塞)
    }else
    {
        attr.c_cc[VMIN] = 0;//没有读到数据也可返回
        attr.c_cc[VTIME] = 2;//单位为100ms -> 0.2s 等待时间
    }
    

    //设置串口属性
    int result = tcsetattr(device->fd, TCSAFLUSH, &attr);
    if (result != 0)
    {
        log_error("设置阻塞模式失败");
    }
        
    log_debug("设置阻塞模式成功");
    return 0;
}

//设置原始模式
int app_serial_setRaw(Device *device)
{
    //获取串口当前配置属性
    struct termios attr;
    
    tcgetattr(device->fd, &attr);

    //修改为原始模式 -> 不解析特殊字符
    cfmakeraw(&attr);

    //设置串口属性
    int result = tcsetattr(device->fd, TCSAFLUSH, &attr);
    if (result != 0)
    {
        log_error("设置原始模式失败");
    }
        
    log_debug("设置原始模式成功");
    return 0;
}

//初始化
int app_serial_init(Device *device)
{
    //进行初始化属性设置
    app_serial_setBaudRate(device, BR_9600); //蓝牙出场默认是9600
    app_serial_setParity(device, Parity_NONE);//不做校验
    app_serial_setStopBits(device, Stop_1);//1个停止位
    // app_serial_setBlock(device, 0);//非阻塞模式(外面单独设置)
    app_serial_setRaw(device);//原始模式

    //刷新后应用配置
    int result = tcflush(device->fd, TCIOFLUSH);
    if (result != 0)
    {
        log_error("串口初始化失败");
        return -1;
    }else
    {
        log_debug("串口初始化成功");
    }

    return 0;

}

//刷新
int app_serial_flush(Device *device)
{
    return tcflush(device->fd, TCIOFLUSH);
}